package com.cn.server.sever;

import com.cn.common.core.codc.RequestDecoder;
import com.cn.common.core.codc.ResponseEncoder;
import com.cn.server.module.player.service.PlayerService;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: jia
 * @Descirption:
 * @Date: 2018/5/18 9:33
 * @Modified By:
 */

//@Component
public class Server1 {
    private PlayerService playerService;
    NioEventLoopGroup boss = new NioEventLoopGroup();
    NioEventLoopGroup woker = new NioEventLoopGroup();
    final NioEventLoopGroup service = new NioEventLoopGroup();
    //@PostConstruct
    public void start() {
        ServerBootstrap b = getBootstrap();
        getCloneBootStrap(b);

    }

    private void getCloneBootStrap(ServerBootstrap b){
        ServerBootstrap clone = b.clone();
        clone.localAddress(10103);
        clone.childHandler(new ChannelInitializer<SocketChannel>() {

            @Override
            public void initChannel(SocketChannel ch) throws Exception {
                ChannelPipeline pipeline = ch.pipeline();
                //======================= websocket =======================///
                IdleStateHandler idleStateHandler = new IdleStateHandler(50, 50, 100);
                pipeline.addLast(idleStateHandler);
                pipeline.addLast(new HttpServerCodec());
                //创建一个http协议的编解码器
                //以块的方式来写的处理器
                pipeline.addLast(new ChunkedWriteHandler());
                //netty是基于分段请求的，HttpObjectAggreator的作用是将
                //请求分段再聚合，参数是聚合字节的最大长度
                pipeline.addLast(new HttpObjectAggregator(8192));
                //创建一个http请求Handler
                //ws://server:port/context_path
                //ws://localhost:9999/ws
                //参数指的是contex_path
                pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
                //帧的传输类型，这里使用的是处理文本类型的Handler
                System.out.println("pipeline:"+Thread.currentThread().getName());


            }
        });
        try {
            clone.bind(new InetSocketAddress(10103)).sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private ServerBootstrap getBootstrap() {
        ServerBootstrap b = null;
        try {

            b = new ServerBootstrap();
            b.group(boss, woker);
            b.localAddress(10102);
            b.channel(NioServerSocketChannel.class);
            b.childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    ChannelPipeline pipeline = ch.pipeline();
                    //======================== 自定义的协议 =====================////
                    //encoer按照ChannelOutboundHandler，逆序执行
                    //decoder按照ChannelIntboundHandler，按照顺序执行
                    IdleStateHandler idleStateHandler = new IdleStateHandler(10, 10, 20);
                    pipeline.addLast(idleStateHandler);
                    pipeline.addLast(new RequestDecoder());
                    pipeline.addLast(new ResponseEncoder());
                    pipeline.addLast(service,new ServerHandler(playerService));

                }
            });

            //设置tcp参数
            b.option(ChannelOption.SO_BACKLOG, 2048);
            b.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
            ChannelFuture future = b.bind().sync();
            System.out.println("Server===start");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return b;
    }
}
